package com.rent.message.interceptor;

import com.rent.common.entity.UserVo;
import com.rent.common.exception.BusinessException;
import com.rent.common.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import java.util.Map;

@Component
@Slf4j
public class WebSocketAuthInterceptor implements HandshakeInterceptor {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, 
                                   WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        log.info("WebSocket握手请求: URI={}, Headers={}", request.getURI(), request.getHeaders());

        // 从请求参数中获取token
        String token = getTokenFromRequest(request);
        
        if (!StringUtils.hasText(token)) {
            log.warn("WebSocket连接拒绝: 未提供token");
            return false;
        }

        // 验证token有效性
        UserVo user = validateToken(token);
        if (user == null) {
            log.warn("WebSocket连接拒绝: 无效的token");
            return false;
        }

        // 将用户信息存入attributes，供后续使用
        attributes.put("userId", user.getId().toString());
        attributes.put("username", user.getUsername());
        attributes.put("token", token);
        
        log.info("WebSocket连接认证通过: userId={}", user.getId());
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, 
                               WebSocketHandler wsHandler, Exception exception) {
        // 握手后的处理，可选
    }

    /**
     * 从请求中获取token
     */
    private String getTokenFromRequest(ServerHttpRequest request) {
        // 详细打印所有headers
//        log.info("=== 所有请求头 ===");
//        request.getHeaders().forEach((key, value) -> {
//            log.info("Header: {} = {}", key, value);
//        });
//        log.info("=== 结束 ===");

        // 1. 从STOMP header中获取
        String stompTokenHeader = request.getHeaders().getFirst("Authorization");
        log.info("Authorization头: {}", stompTokenHeader);

        if (StringUtils.hasText(stompTokenHeader) && stompTokenHeader.startsWith("Bearer ")) {
            String token = stompTokenHeader.substring(7);
            log.info("从Authorization头获取到token: {}", token);
            return token;
        }

        // 2. 从自定义header获取
        String customToken = request.getHeaders().getFirst("X-Auth-Token");
        log.info("X-Auth-Token头: {}", customToken);
        if (StringUtils.hasText(customToken)) {
            return customToken;
        }

        // 3. 从查询参数获取
        String query = request.getURI().getQuery();
        log.info("查询参数: {}", query);
        if (StringUtils.hasText(query)) {
            for (String param : query.split("&")) {
                String[] keyValue = param.split("=");
                if (keyValue.length == 2 && "token".equals(keyValue[0])) {
                    String token = keyValue[1];
                    log.info("从查询参数获取到token: {}", token);
                    return token;
                }
            }
        }

        log.warn("未找到token");
        return null;
    }

    /**
     * 验证token有效性
     */
    private UserVo validateToken(String token) {
        try {
            // 从Redis中验证token
            String userTokenKey = "user:token:" + token;

            UserVo user = (UserVo)redisTemplate.opsForValue().get(userTokenKey);
//            UserVo user = redisUtil.get(userTokenKey, UserVo.class);

            if(user != null){
                return user;
            }else {
                throw new BusinessException("用户消息连接认证失败");
            }
            
            // 如果Redis中没有，可以尝试其他验证方式，比如JWT解析
            // 这里可以根据您的具体token实现来调整
        } catch (Exception e) {
            log.error("token验证失败", e);
            return null;
        }
    }
}